from time import timezone

from decimal import Decimal
from django_redis import get_redis_connection
from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo, OrderGoods
from django.db import transaction

class OrderPlaceSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1, label='数量')
    class Meta:
        model = SKU
        fields = ('default_image_url', 'name', 'price', 'count', 'id')


class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('address', 'pay_method', 'order_id')

        read_only_fields = ['order_id']
        extra_kwargs = {
            'address': {
                'write_only': True,
            },
            'pay_method': {
                'write_only': True,
            }
        }

    # 重写create方法,去除redis数据,创建订单对象,订单商品对象
    #TODO 开启事务
    @transaction.atomic
    def create(self, validated_data):
        # 获取user
        user = self.context['request'].user
        # 创建订单编号,尽量保持唯一性
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d" % user.id
        # 获取地址
        address = validated_data['address']
        # 获取支付方式
        pay_method = validated_data['pay_method' ]

        # 订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        # TODO: 设置保存点
        sid = transaction.savepoint()
        # 创建订单信息对象
        order = OrderInfo.objects.create(
            order_id=order_id,
            user=user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10.0),
            pay_method=pay_method,
            status=status
        )

        # 获取redis中的数据
        redis_conn = get_redis_connection('cart')
        cart_dict = redis_conn.hgetall('cart_%s' % user.id)
        cart_selected_list = redis_conn.smembers('cart_selected_%s' % user.id)
        # 遍历获取创建订单商品信息
        for sku_id in cart_selected_list:
            # TODO:使用乐观锁解决并发订单问题后,若订单库存足够仍然能够下单
            while True:
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                if count > sku.stock:
                    # TODO: 事务回滚
                    transaction.savepoint_rollback(sid)
                    raise serializers.ValidationError("商品库存不足")
                # 减少库存,增加销量
                # TODO: 使用乐观锁解决并发提交订单,库存量冲突问题
                #
                # sku.stock -= count
                # sku.sales += count
                # sku.save()
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count
                new_sales = old_sales + count
                ret = SKU.objects.filter(id=sku.id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                if ret == 0:
                    # raise serializers.ValidationError('下单失败')
                    # 继续查询下一次库存
                    continue
                # 累加商品数量以及价格
                order.total_count += count
                order.total_amount += (sku.price * count)
                # 创建订单商品对象
                order_goods = OrderGoods.objects.create(order=order, sku=sku, count=count,
                                          price=sku.price)
                # 订单查询成功必须退出,否则一直在循环
                break

        order.save()
        # TODO: 事务提交
        transaction.savepoint_commit(sid)
        redis_conn.hdel('cart_%s' % user.id, *cart_selected_list)
        redis_conn.srem('cart_selected_%s' % user.id, * cart_selected_list)

        return order



